<html>
<head>
<title>Troubleshooting log4j</title>
</head> 
<body bgcolor=#FFFFFF>
 
    <h1 align=center>Log4j troubleshooting</h1>

    <h2 align=center>Ceki G&uuml;lc&uuml; Paul Glezen
      <br/>February 2002
    </h2>
 
    <hr/>

      <p>Here is a list of commonly encountered problems when using log4j:</p>
	
      <ul> 
	
	<li><p><a href=#noAppenders>log4j tells me to initialize
	      properly.</a></p>
	</li>

	<li><p><a href=#duplicates>Duplicates in log4j output.</a></p>
	</li>
	<li><p><a href=#space>Options are not parsed correctly.</a></p>
	</li>
	<li><p><a href=#jit>Caller location information is printed as a "?"
	      character.</a>
	  </p>
	</li>

	<li><p><a href=#cce>ClassCastException when instantiating a Category subclasses.</a>
	  </p>
	</li>


	<li><p><a href="#notfound">My EJB-Servlet-JSP says log4j class
        not found or not defined.</a> </a></p>
        </li>
	
	<li><p><a href=#syslogd>I cannot connect to syslogd under linux.</a>
	  </p></li>

	<li><p><a href="#nosuchpropperty">log4j:WARN No such property
	      [xyz] in some.appender.or.layout</a>
	  </p>
	</li>    
      </ul>

      <hr>

	<p><a name="noAppenders"></a><h4>log4j tells me to initialize properly.</h4>

	  Logging output is written to a target by using an appender. If no
	  appenders are attached to a category nor to any of its ancestors, you
	  will get the following message when trying to log:
	</p>

<pre>
log4j: No appenders could be found for category (some.category.name).
log4j: Please initialize the log4j system properly.
</pre>

	<p><em>Log4j does not have a default logging target.</em>
	  It is the user's responsibility to ensure that all
	  categories can inherit an appender.  This can be easily
	  achieved by attaching an appender to the root category.</p>


	<p><a name=duplicates></a><h3>Duplicates in log4j output.</h3></p>

	<p>The reason for observing duplicates in log4j output is
	  either due to having added the same appender multiple times
	  to the same category (typically root) or having added the
	  same appender to different categories ignoring the fact that
	  appenders are inherited cumulatively.</p>

	<p>log4j does not eliminate appender duplicates. In other
	  words, if you add the same appender to a category <i>n</i>
	  times, that appender will be invoked <i>n</i> times to
	  append to its target. </p>

	<p>A slightly different cause is adding different appenders
	  all sharing the same underlying output target to some
	  category. In the most common occurrence of this phenomenon,
	  the BasicConfigurator.configure() method is invoked multiple
	  times. Each time it is invoked, this method adds an appender
	  with a <code>System.out</code> target to the root
	  category. </p>

	<p>One other common mistake is to forget that appenders are
	  inherited cumulatively from the hierarchy. For example, if
	  you add an appender, say <code>A</code>, to the root
	  category, all other categories will inherit <code>A</code>
	  as an appender. Thus, if you add <code>A</code> to a
	  category, say <code>C</code>, then an enabled statement of
	  category <code>C</code>, will print to <code>A</code> twice,
	  once because <code>A</code> is in root and once because it
	  is in <code>C</code>. </p>

	<p><a name=space></a><h3>Options are not parsed correctly.</h3>

	  <p>The PropertyConfigurator relies on
	    <code>java.util.Properties</code> class to read in the
	    configuration file. This class preserves spaces in
	    options. For example,</p>

<pre>
fruit=orange  
</pre>
is returned as an option having the key <code>"fruit"</code> and the
	  value <code>"orange "</code>.</p>

	<p>The spaces in the value, i.e. <code>"orange "</code>, are due to
	  invisible spaces at the end of the example shown above. Thus, some of
	  the options might not be interpreted correctly due to trailing
	  spaces. </p>

	<p><a name=jit></a><h3>Caller location information is printed as a "?"
	    character.</h3>
	  
	  Location information is extracted automatically by the PatternLayout
	  conversion patterns %C, %F, %M and %L. However, some just-in-time
	  (JIT) compilers make it impossible to extract location information. It
	  is also possible that the compiler that generated the byte code may
	  have omitted the LineNumber table as is done by -O option of javac
	  and jikes. </p>

	<p>You can remedy this problem by disabling the JIT compiler and by
	  compiling the code without the -O option.</p>
	
	<p><b>In wrappers or subclasses of Category </b>

	  <p>Wrappers or subclasses of <code>Category</code> need supply their
	    fully qualified class name to the <code>Category.log</code> method or
to <code>Category.forcedLog</code> methods so that the caller location
information can be extracted correctly.</p>

	  <p>This approach will work correctly in all cases except if
	    the class invoking the extended category instance has the
	    same prefix as the extended category class. For example,
	    calling an instance of <code>com.foo.BarCategory</code>
	    from the <code>com.foo.BarCategoryTest</code> class will
	    not yield the correct caller information. To circumvent
	    this "bug", either perform the tests from a class with a
	    different name or add a dot to the fully qualified name of
	    the extending class that you supply to
	    <code>Category.log</code> to
	    <code>Category.forcedLog</code> methods. For the
	    <code>com.foo.BarCategory</code> example, supply the
	    string <code>"com.foo.BarCategory."</code>.</p>


	  <p><a name=cce><h3><code>ClassCastException</code> when
instantiating a <code>Category</code> subclasses.</a></h3>

	    <p>This exception is thrown because log4j does not support
homonyms. For example, the following will systematically throw a
<code>ClassCastException</code></p>

<pre>
  Category c1 = Category.getInstance("bad");
  MyCategory c2 = (MyCategory) MyCategory.getInstance("bad");
</pre>

where <code>MyCategory</code> is a subclass of
<code>Category</code>. The problem occurs because the second
<code>getInstance</code> invocation will retrieve the category created
in the fist invocation. This instance is a <code>Category</code>
object and cannot be cast to <code>MyCategory</code>.</p>
	  
	  <p>By default, the <code>PropertyConfigurator</code> will
	    create and configure
	    <code>org.apache.log4j.Category</code> objects. Thus, if
	    you try to instantiate a category subclass for an already
	    existing category, and try to cast it to the subclass
	    type, you will systematically get a
	    <code>ClassCastException</code>.</p>

	  <p>To address this problem, the
	    <code>PropertyConfigurator</code> admits the
	    <code>log4j.categoryFactory</code> key. The value of this
	    key will be used as the factory to invoke when
	    instantiating Category objects.

	    <p>The <code>DOMConfigurator</code> has a finer grain
	      method for setting the class of the category object to instantiate.


<!-- <a name="#levelCast"><h3>Compilation errors when using <code>setLevel(org.apache.log4j.Level)</code> from the Category class.</h3>

  <p>If you try to call the setLevel method with one of the built in
  levels, the java compiler with complain:

<pre>
  [javac] setLevel(org.apache.log4j.Level) in org.apache.log4j.Category cannot be applied to (org.apache.log4j.Priority)
  [javac]         logger.setLevel(Level.DEBUG);
</pre>
where logger is a variable of type Logger.

   <p>Casting any of the Level.DEBUG, Level.INFO, Level.WARN,
Level.ERROR, Level.FATAL arguments to Level will make the compiler
happy.  As in <pre> logger.setLevel(<b>(Level)</b> Level.DEBUG);
</pre>

			  <p>This cast is always safe because log4j 1.2 will never produce
anything but <code>Level</code> objects, never <code>Priority</code>
objects. Surprisingly enough this cast was not necessary in log4j 1.2
alpha. It is required in 1.2 beta and later to ensure runtime
compatibility with log4j 1.1.3.</p>

-->

<p><a name=notfound><h3>Log4j class not found/defined</h3>

<p>Naturally you should check the classpath.  But you should also 
be aware of the presence of multiple classloaders in the JVM:
<p> <ol>
<li>the bootstrap classloader
<li>the extension classloader
<li>the application classloader
</ol>
<p>If you place log4j.jar in the <code>jre/lib/ext</code> directory
but place user-defined extensions to log4j in the application 
classloader classpath, log4j configurators will not find them.

<p>Servlet, JSP and EJB containers inside of application servers
usually have their own special classloaders in addition to the 
three mentioned above.  While this provides for a greater
degree of separation for different webapps, EJB containers and the
application server runtime itself, it can provide headaches to the
uninitiated.

<p>Classloaders are usually hierarchically related.  The bootstrap
loader forms the root with the extension loader as its child.  The
application loader is the child of the extension loader and it's
this "app loader" that we use by default when we write standalone
Java programs.

<p>Upon receiving a class load request, the classloader usually 
delegates it to the parent before attempting to service the request.
This allows the bootstrap and extension loaders to deliver any classes
that are part of the JDK or its extensions.  Only after this delegation
fails will the classloader attempt to find the class itself.  Note that
classloaders do not delegate requests to children.

<p>Application servers often use the application loader for its runtime
classes and create separate classloaders for its webapp and EJB
containers.  These additional classloaders may descend directly
from the app server's runtime classloader.  If log4j is placed in the
classpath of a webapp classloader, another webapp classloader will not
necessarily see it.  EJBs wouldn't see it either.  If log4j is intended
to be made available to all objects participating in the app server, it
should be included in the classpath of a classloader high enough in the
classloader hierarchy to be seen by all classloaders.

<p>A good article on classloaders with examples using IBM's WebSphere
application server can be found 
<a href="http://www7.software.ibm.com/vadd-bin/ftpdl?1/vadc/wsdd/pdf/gisell/UnderstandingWebSphereClassLoaders.pdf">here</a> 
in PDF format.

<h3><p><a name="syslogd">I cannot log to syslogd under linux.</a></h3>

If you are trying to log to the Unix syslog under Linux using the <a
href="api/org/apache/log4j/net/SyslogAppender.html">SyslogAppender</a>,
then the Linux syslog daemon must be configured to accept log input
from the network.  Otherwise, you will get an <code>IOException:
connection refused</code>.

<p>This can be done by adding the <code>-r</code> option when starting
the daemon. Or more precisely:

<ol>
<li>Login as the <code>root</code> user
<li>Edit file <code>/etc/rc/init.d/syslog</code>
<pre>
case "$1" in
  start)
        echo -n "Starting system logger: "
        daemon syslogd -r
</pre>

<li><code>/etc/rc/init.d/syslog restart</code>

</ol>

<p><a name=#nosuchpropperty><h3>log4j:WARN No such property [xyz] in some.appender.or.layout</h3>

<p>If during log4j configuration you get a warning about an inexistent
property, then you have probably misspelled a property or entered a
truly unrecognized property for the component you are trying to
configure in the configuration file.

<p>Log4j version 1.0 did not complain about unrecognized properties
whereas log4j version 1.1 and later do complain.




</body>
</html>
